import java.util.ArrayList;
import javax.swing.*;
import java.io.*;

public class Location implements Entity, Serializable {

	protected String DisplayName;
	protected String Description;
	protected String Orientation;
	protected ArrayList<Entity> Inventory = new ArrayList<Entity>();
	protected boolean CanBePickedUp = false;
	protected String Why = "How would that work, exactly?\n\n";
	private ArrayList<Entity> Decorations = new ArrayList<Entity>();
	private ArrayList<Entity> Items = new ArrayList<Entity>();
	private ArrayList<Entity> Exits = new ArrayList<Entity>();
	private ArrayList<Character> Characters = new ArrayList<Character>();
	private StaticObject toomany = new StaticObject("toomany", "toomany", "toomany", "toomany");
	private boolean isVisible;
	private int value;
	private History history;
	private boolean isBed = false;
	private double Weight;
	private int Gold;
	private boolean isShop;
	private boolean forSale;
	private Locale locale;
	
	public Location(String a, String c) {
		DisplayName = a;
		Description = c;
		isVisible = true;
		Weight = 0.0;
		Gold = 0;
		isShop = false;
		forSale = false;
	}
	
	public Character findMerchant() {
		Character result = null;
		for (Character a : Characters) {
			if (a.isMerchant() == true) {
				result = a;
			}
		}
		return result;
	}
	
	public void setLocale(Locale a) {
		locale = a;
	}
	
	public Locale getLocale() {
		return locale;
	}
	
	public void modifyGold(int a) {
		Gold = Gold + a;
	}
	
	public void isShop(Character a) {
		isShop = true;
		a.isMerchant(true);
		for (Entity item : Items) {
			item.forSale(true);
		}
		for (Entity decoration : Decorations) {
			for (Entity item : decoration.getInventory()) {
				item.forSale(true);
			}
		}
		
	}
	
	public void notShop() {
		isShop = false;
		for (Entity item : Items) {
			item.forSale(false);
		}
		for (Entity decoration : Decorations) {
			for (Entity item : decoration.getInventory()) {
				item.forSale(false);
			}
		}
	}
	
	public boolean isShop() {
		return isShop;
	}
	
	public void forSale(boolean a) {
		forSale = a;
	}
	
	public boolean isForSale() {
		return forSale;
	}
	
	public int getGold() {
		return Gold;
	}
	
	
	public void addEntity(Entity a) {
		if (a.getClass().getName().equalsIgnoreCase("StaticObject")) {
			Decorations.add(a);			
		} else if (a.getClass().getName().equalsIgnoreCase("Item") || a.getClass().getName().equalsIgnoreCase("Weapon") || a.getClass().getName().equalsIgnoreCase("Consumable") || a.getClass().getName().equalsIgnoreCase("Armour")) {
			Items.add(a);
		} else if (a.getClass().getName().equalsIgnoreCase("Exit")) {
			Exits.add(a);
		}
	}
	
	public void addHistory(History a) {
		history = a;
	}
	
	public void addCharacter(Character a) {
		Characters.add(a);
		a.setLocation(this);
	}
	
	public Entity getKey() {
		return null;
	}
	
	public void lock() {
		
	}
	
	public void unlock() {
		
	}
	
	
	public void Display(JTextArea y) {
		y.append("You are in " + DisplayName + ". " + Description + "." + "\n");
		for (Entity a : Decorations) {
			a.Display(y);
		}
		
		for (int i = 0; i < Items.size(); i++) {
			if (i == 0) {
				if (i < Items.size() - 1) {
				Items.get(i).Display(y);
				} else {
					Items.get(i).Display(y);
					y.append(". ");
				}
			} else if (i > 0 && i < (Items.size() - 1)) {
				y.append(", " + Items.get(i).getDisplayName());
			} else if (i == Items.size() - 1){
				y.append(" and " + Items.get(i).getDisplayName() + ". ");
			}
		}
		
		for (Entity c : Exits) {
			c.Display(y);
		}
		
		for (Entity d : Characters) {
			d.Display(y);
		}
		
		if (Gold > 0) {
			y.append("On the floor is " + Gold + " gold.");
		}
	}
	
	public void setGold(int a) {
		Gold = a;
	}
	
	public void Describe(JTextArea y) {
		y.append("You are in " + DisplayName + ". " + Description + "\n");
		
		for (Entity a : Decorations) {
			a.Display(y);
		}
		
		for (Entity b : Items) {
			b.Display(y);
		}
				
	}
	
	public Entity findObject(String a) {
		Entity entity = null;
		int counter = 0;
		
		for (Entity b : Decorations) {
			if (b.getDisplayName().contains(a) && b.isVisible() == true) {
				entity = b;
				counter++;
			} else {
				for (Entity c : b.getInventory()) {
					if (c.getDisplayName().contains(a) && c.isVisible() == true || a.contains(c.getDisplayName()) && c.isVisible() == true) {
						entity = c;
						counter++;
					} else {
						for (Entity pp : c.getInventory()) {
							if (pp.getDisplayName().contains(a) && pp.isVisible() == true || a.contains(pp.getDisplayName()) && pp.isVisible() == true) {
								entity = pp;
								counter++;
							}
						}
					}
				}
			}
		}
		
		for (Entity e : Items) {
			if (e.getDisplayName().contains(a) && e.isVisible() == true || a.contains(e.getDisplayName()) && e.isVisible() == true) {
				entity = e;
				counter++;
			}
		}
		
		for (Entity d : Exits) {
			if ((d.getName().contains(a))  || (d.getOrientation().equalsIgnoreCase(a)) || a.contains(d.getName()) && d.isVisible() == true) {
				entity = d;
				counter++;
			}
		}
		
		for (Entity f : Characters) {
			if ((f.getName().contains(a)) || (a.contains(f.getName())) && f.isVisible() == true) {
				entity = f;
				counter++;
			} else {
				for (Entity g : f.getInventory()) {
					if (g.getName().contains(a) || a.contains(g.getName())) {
						
						if (g.isVisible() == true) {
						entity = g;
						counter++;
						}
					}
				}
			}
		}
		
		if (counter > 1) {
			return toomany;
		} else {
		return entity;
		}
	}
	
	public Exit findExit(String a) {
		Exit result = null;
		int counter = 0;
		for (Entity d : Exits) {
			if ((d.getName().contains(a)) || (d.getOrientation().equalsIgnoreCase(a)) || a.contains(d.getName()) && d.isVisible() == true) {
				result = (Exit)d;
				counter++;
			}
		}
		
		if (counter > 1) {
			System.out.print("You can see more than one " + a + ". Please be more specific.");
		}
		return result;
	}

	public void removeObject(String a) {
		for (Entity b : Decorations) {
			if (b.getDisplayName().contains(a) && b.isVisible() == true || a.contains(b.getDisplayName()) && b.isVisible() == true) {
				Decorations.remove(b);
				break;
			}
			
			for (Entity c : b.getInventory()) {
				if (c.getDisplayName().contains(a) && c.isVisible() == true || a.contains(c.getDisplayName()) && c.isVisible() == true) {
					b.removeObject(c);
					break;
				}
			}
		}
			
			for (Entity d : Items) {
				if (d.getDisplayName().contains(a) && d.isVisible() == true || a.contains(d.getDisplayName()) && d.isVisible() == true) { 
					Items.remove(d);
					break;
				}
			}
			
			for (Entity e : Exits) {
				if (e.getName().contains(a) || a.contains(e.getName())) {
					Exits.remove(e);
					break;
				}
			}
			
			for (Entity f : Characters) {
				if (f.getName().contains(a) || a.contains(f.getName())) {
					Characters.remove(f);
					break;
				}
			
			
				for (Entity g : f.getInventory()) {
					if (g.getName().contains(a) || a.contains(g.getName())) {
						f.removeObject(g);
						break;
					}
				}
			}
		}
		
		
	public int getValue() {
		return value;
	}
	
	public void setValue(int a) {
		value = a;
	}

	
	public void removeSpecificObject(Entity a, Entity x) {
		for (Entity b : Decorations) {
			if (b.getName().contains(a.getName()) && b.getOrientation().equalsIgnoreCase(a.getOrientation()) && b.isVisible() == true) {
				Decorations.remove(b);
				break;
			}
			
			for (Entity c : b.getInventory()) {
				if (c.getName().contains(a.getName()) && c.getOrientation().equalsIgnoreCase(a.getOrientation()) && c.isVisible() == true && b == x) {
					b.removeObject(c);
					break;
				}
			}
			
			for (Entity d : Items) {
				if (d.getName().contains(a.getName()) && d.getOrientation().equalsIgnoreCase(a.getOrientation()) && d.isVisible() == true) {
					Items.remove(d);
					break;
				}
			}
			
			
		}
		
		
	}
	
	public Character findCharacter(String a) {
		Character result = null;
		for (Entity b : Characters) {
			if (b.getName().contains(a) || a.contains(b.getName()) && b.isVisible() == true) {
				result = (Character) b;
			} else {
				
			}
		}
		
		return result;
	}
	
	
	public Entity findSpecificObject(String Target, String Orientation, String Place, Player player) {
	
		Entity result = null;
		int counter = 0;
		
		if (Place.equalsIgnoreCase("inventory")) {
			for (Entity a : player.getInventory()) {
				if (a.getName().contains(Target) && a.isVisible() == true || Target.contains(a.getName()) && a.isVisible() == true) {
					result = a;
					counter++;
				}
			}
			
			if (result == null) {
				if (player.get_Main_Hand().getName().contains(Target)) {
					result = player.get_Main_Hand();
				} else if ((player.getHead() != null) && (player.getHead().getName().contains(Target))) {
					result = player.getHead();
				} else if ((player.getShoulders() != null) && (player.getShoulders().getName().contains(Target))) {
					result = player.getShoulders();
				} else if ((player.getChest() != null) && (player.getChest().getName().contains(Target))) {
					result = player.getChest();
				} else if ((player.getHands() != null) && (player.getHands().getName().contains(Target))) {
					result = player.getHands();
				} else if ((player.getLegs() != null) && (player.getLegs().getName().contains(Target))) {
					result = player.getLegs();
				} else if ((player.getFeet() != null) && (player.getFeet().getName().contains(Target))) {
					result = player.getFeet();
				}
			}
			
		} else {
		
		for (Entity a : Decorations) {
			if (a.getName().equalsIgnoreCase(Place) && a.isVisible() == true || Place.contains(a.getName()) && a.isVisible() == true) {
				for (Entity b : a.getInventory()) {
					if (b.getName().contains(Target) && (b.getOrientation().equalsIgnoreCase(Orientation)) && b.isVisible() == true) {
						result = b;
						counter++;
					}
				}
			}
		}
		}
		
		if (counter > 1) {
			return toomany;
		} else {
		return result;
		}
		
	}
	
	public ArrayList<Entity> getInventory() {
		return Inventory;
	}
	
	public void removeObject(Entity a) {
		Inventory.remove(a);
		for (Entity b : Decorations) {
			b.removeObject(a);
		}
	}	
	
	public String getOrientation() {
		return Orientation;
	}
	
	public void setOrientation(String a) {
		Orientation = a;
	}
	
	public String getDisplayName(){
		return DisplayName;
	}
	
	public String getName() {
		return null;
	}
	
	public String getDescription() {
		return Description;
	}
	
	public void Use(Player a, String b, JTextArea y, JTextField x) {		
	}
	
	public boolean TestCanBePickedUp() {
		return CanBePickedUp;
	}
	
	public void CantBePickedUp(String b) {
		CanBePickedUp = false;
		Why = b;		
	}
	
	public String CanBePickedUp_Why() {
		return Why;
	}
	
	public void printInventory(JTextArea x) {
		
	}
	
	public void setVisible(boolean a) {
		isVisible = a;
	}
	
	public boolean isVisible() {
		return isVisible;
	}
	
	public void setContentsVisible(boolean a) {
		for (Entity b : Inventory) {
			b.setVisible(true);
		}
	}
	
	public boolean isLocked() {
		return false;
	}
	
	public History getHistory() {
		return history;
	}
	
	public void Link(Location destination, String direction, String name, String description, boolean e, Entity ... key) {
		String opposite = null;
		if (direction.equalsIgnoreCase("North")) {
			opposite = "south";
		} else if (direction.equalsIgnoreCase("South")) {
			opposite = "north";
		} else if (direction.equalsIgnoreCase("East")) {
			opposite = "west";
		} else if (direction.equalsIgnoreCase("West")) {
			opposite = "east";
		} else if (direction.contains("up")) {
			direction.replace("up", "down");
		} else if (direction.contains("down")) {
			direction.replace("down", "up");
		}
			this.addEntity(new Exit(direction, name, description, destination));
			destination.addEntity(new Exit(opposite, name, description, this));
			if (key.length > 0) {
				this.findExit(direction).NeedsKey(key[0]);
				this.findExit(direction).StartsLocked(e);
				destination.findExit(opposite).NeedsKey(key[0]);
				destination.findExit(opposite).StartsLocked(false);
			}
	}
	
	public boolean isBed() {
		return isBed;
	}
	
	public void isBed(boolean a) {
		isBed = a;
	}
	
	public double getWeight() {
		return Weight;
	}

	
}
